feat: add Alpine image#1949
Conversation
There was a problem hiding this comment.
Pull request overview
Adds an Alpine-based Docker image variant for prek (to cover common hook runtime dependencies) and updates docs/CI publishing to support it.
Changes:
- Document two published images (
scratchminimal andalpine) in Docker integration docs. - Extend the root
Dockerfilewith analpine:3.23target that installs common hook dependencies and includes theprekbinary. - Update the Docker build/publish GitHub Actions workflow to build and publish both
minimalandalpineimage variants for multiple platforms.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
docs/integrations.md |
Documents the new ghcr.io/j178/prek-alpine image and clarifies the minimal scratch image section. |
Dockerfile |
Adds minimal and alpine build targets; Alpine target installs common hook dependencies and copies prek to /usr/local/bin. |
.github/workflows/build-docker.yml |
Builds/publishes both image variants across linux/amd64 and linux/arm64, and separates digest artifacts per image+platform. |
| @@ -87,10 +99,11 @@ jobs: | |||
| with: | |||
| context: . | |||
| platforms: ${{ matrix.platform }} | |||
| cache-from: type=gha,scope=prek-${{ env.PLATFORM_TUPLE }} | |||
| cache-to: type=gha,mode=min,scope=prek-${{ env.PLATFORM_TUPLE }} | |||
| target: ${{ matrix.image }} | |||
| cache-from: type=gha,scope=prek-${{ matrix.image }}-${{ env.PLATFORM_TUPLE }} | |||
| cache-to: type=gha,mode=min,scope=prek-${{ matrix.image }}-${{ env.PLATFORM_TUPLE }} | |||
| labels: ${{ steps.meta.outputs.labels }} | |||
| outputs: type=image,name=${{ env.PREK_BASE_IMG }},push-by-digest=true,name-canonical=true,push=${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }} | |||
| outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }} | |||
There was a problem hiding this comment.
IMAGE_NAME is set via $GITHUB_ENV in a previous step, but later you reference it via the expression context (${{ env.IMAGE_NAME }}) in with: inputs. Environment variables written to $GITHUB_ENV are available to subsequent run: steps, but they are not reliably available for expression evaluation in later steps, which can cause images:/outputs: to be empty or incorrect. Prefer computing the image name directly in the expression (e.g., conditional on matrix.image), or set it as a step output and reference steps.<id>.outputs.* instead.
| @@ -136,7 +163,7 @@ jobs: | |||
| env: | |||
| DOCKER_METADATA_ANNOTATIONS_LEVELS: index | |||
| with: | |||
| images: ${{ env.PREK_BASE_IMG }} | |||
| images: ${{ env.IMAGE_NAME }} | |||
| # Order is on purpose such that the label org.opencontainers.image.version has the first pattern with the full version | |||
| tags: | | |||
| type=raw,value=${{ fromJson(inputs.plan).announcement_tag }} | |||
| @@ -151,27 +178,23 @@ jobs: | |||
| # Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/ | |||
| - name: Create manifest list and push | |||
| working-directory: /tmp/digests | |||
| # The jq command expands the docker/metadata json "tags" array entry to `-t tag1 -t tag2 ...` for each tag in the array | |||
| # The printf will expand the base image with the `<PREK_BASE_IMG>@sha256:<sha256> ...` for each sha256 in the directory | |||
| # The final command becomes `docker buildx imagetools create -t tag1 -t tag2 ... <PREK_BASE_IMG>@sha256:<sha256_1> <PREK_BASE_IMG>@sha256:<sha256_2> ...` | |||
| run: | | |||
| # shellcheck disable=SC2046 | |||
| readarray -t lines <<< "$DOCKER_METADATA_OUTPUT_ANNOTATIONS"; annotations=(); for line in "${lines[@]}"; do annotations+=(--annotation "$line"); done | |||
|
|
|||
| docker buildx imagetools create \ | |||
| "${annotations[@]}" \ | |||
| $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ | |||
| $(printf "${PREK_BASE_IMG}@sha256:%s " *) | |||
| $(printf "${IMAGE_NAME}@sha256:%s " *) | |||
|
|
|||
| - name: Export manifest digest | |||
| id: manifest-digest | |||
| env: | |||
| IMAGE: ${{ env.PREK_BASE_IMG }} | |||
| VERSION: ${{ steps.meta.outputs.version }} | |||
| run: | | |||
| digest="$( | |||
| docker buildx imagetools inspect \ | |||
| "${IMAGE}:${VERSION}" \ | |||
| "${IMAGE_NAME}:${VERSION}" \ | |||
| --format '{{json .Manifest}}' \ | |||
| | jq -r '.digest' | |||
| )" | |||
| @@ -180,5 +203,5 @@ jobs: | |||
| - name: Generate artifact attestation | |||
| uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0 | |||
| with: | |||
| subject-name: ${{ env.PREK_BASE_IMG }} | |||
| subject-name: ${{ env.IMAGE_NAME }} | |||
| subject-digest: ${{ steps.manifest-digest.outputs.digest }} | |||
There was a problem hiding this comment.
Same issue as in the build job: IMAGE_NAME is set via $GITHUB_ENV, but later used in expression contexts (${{ env.IMAGE_NAME }}) for docker/metadata-action and actions/attest. This can result in publishing/attesting with an empty or wrong image name. Compute IMAGE_NAME via expressions (based on matrix.image) or expose it as a step output and reference steps.<id>.outputs.image_name.
| py3-pip | ||
| COPY --from=build /prek /usr/local/bin/prek | ||
| WORKDIR /io | ||
| ENTRYPOINT ["prek"] |
There was a problem hiding this comment.
Because the alpine stage is now the last stage in the Dockerfile, running docker build . without --target will produce the Alpine image rather than the previously default scratch/minimal image. If consumers rely on the default being the minimal image, consider keeping the minimal stage as the final/default stage (e.g., add a final FROM minimal stage at the end, or reorder stages) while still allowing --target alpine for the Alpine variant.
| ENTRYPOINT ["prek"] | |
| ENTRYPOINT ["prek"] | |
| FROM minimal |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1949 +/- ##
=======================================
Coverage 93.25% 93.25%
=======================================
Files 127 127
Lines 27988 27988
=======================================
Hits 26099 26099
Misses 1889 1889 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Sorry for the back and forth here. After thinking more about the long-term maintenance tradeoff, I think the official That keeps the image contract clear: we ship the Thanks again for the proposal and the PR. I’m going to close this and #1946 for now. |
|
Uff, that's quite a bummer. I didn't mean to replace the scratch image, just add an Alpine one on the side which will save multiple seconds and bandwith in CI on every run. There's almost no effort to build these in addition to the already existing base image. It's easy to do this in the main source repo. By denying this, you indirectly force many individual's to build the same images and keep up with releases in a dynamic way etc. That is a lot of (unnecessary) overhead.
A sophisticated use of |
📦 Cargo Bloat ComparisonBinary size change: +0.00% (25.8 MiB → 25.8 MiB) Expand for cargo-bloat outputHead Branch ResultsBase Branch Results |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 233a2b871a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@j178 Tried to make all automated reviewers happy. Would be great if you could take a look again if this would work for you! |
fix #1946